昨日用會員登入註冊的範例,來說明Spring Security符合驗證規則的路由,如何排除特定請求路徑,並使用AuthenticationManager驗證使用者登入,順便說明了IoC和Bean元件的觀念,今天來用管理者帳號的例子,說明使用@Autowride注入介面,如何解決多個實作類別的問題,以及登入使用者角色
為了方便示範,管理者資料表就與 member相同,只修改資料表名稱
CREATE TABLE `admin` (
`id` BIGINT(19) NOT NULL AUTO_INCREMENT,
`account` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`password` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
`name` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB;
由於 Spring Boot 不像 Laravel 提供項 artisan 這類能在終端機執行的指令,為了方便建立帳號,模仿這個設計實現自定義指令,順便學習自動配置的進階用法
實現流程是建一個Package專門放指令,這裡就叫 com.app.console,並在這個Package下負責呼叫執行指令的類別 MainCommand,這裡要添加@ComponentScan並定義Package,用意是在執行Spring Boot時,可以從特定 Package開始掃描Bean元件時,如果沒有特別設定,會從執行 SpringApplication.run方法的Package開始查找Bean元件
@ComponentScan({ "com.app.console", "com.app.demo" })
@SpringBootApplication
public class MainCommand {
public static void main(String[] args) {
try {
/**
* 1. 要執行的指令名稱對應Bean名稱
* 2. 第 0 個參數固定為 指令名稱
*/
String taskName = args[0];
ApplicationContext context = SpringApplication.run(MainCommand.class, args);
Handler handler = (Handler) context.getBean(taskName);
// 第二個參數即執行指令要使用的參數,
List<String> handleArgs = Collections.emptyList();
if (args.length > 1) {
for (int index = 1; index < args.length; index++) {
handleArgs.add(args[index]);
}
}
handler.run(handleArgs);
System.out.println("執行邏輯處理結束");
} catch (Exception ex) {
// 未輸入任務名稱參數或沒有符合的Bean名稱會拋出錯誤,視為無定義指令
System.out.println("執行異常,檢查執行任務是否已定義");
}
System.exit(0);
}
@Bean(name = "CreateAdmin")
public CreateAdmin getHandler() {
return new CreateAdmin();
}
}
同層Package定義邏輯實作的類別,類別名稱即為任務名稱,以及通用介面,規範必須實作run方法的實作
// com.app.console.Handler
interface Handler {
/**
* @param args command 輸入的參數
*
* @return void
*/
public void run(List<String> args);
}
// 指令名稱 CreateAdmin 對應 Bean 名稱
class CreateAdmin implements Handler {
@Autowired
private AdminDao adminDao;
@Autowired
private PasswordEncoder pwdEncoder;
public void run(List<String> args) throws Exception {
// 0跟1為帳號密碼 未輸入表示異常
String account = args.get(0);
String password = args.get(1);
System.out.println("Check Account & Password");
if (account == null || password == null) {
throw new Exception("遺失帳號或密碼");
}
Admin newAdmin = Admin.builder()
.account(account)
.password(pwdEncoder.encode(password))
.name("管理者")
.build();
int result = adminDao.create(newAdmin);
System.out.printf("Add new admin Success status %d\n", result);
}
}
由於 專案目錄下會有多個類使用 @SprongBootApplication 註釋,需要指定起始 class
執行 spring-boot:run 指令才不會有異常,作法是在 properties新增 start-class 屬性
<properties>
<java.version>17</java.version>
<start-class>com.app.demo.DemoApplication</start-class>
</properties>
最後用 mvn 執行Bytecode,指令如下
mvn exec:java -Dexec.mainClass=com.app.console.MainCommand -Dexec.args="CreateAdmin 管理者帳號 密碼"
打開資料庫可以看到,成功建立管理者帳號,完成用終端機操作IoC容器黑魔法